package com.ccrfid.rmc6.resource.personnel;

import com.ccrfid.rmc6.appconfig.auth.Secured;
import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.personnel.*;
import com.ccrfid.rmc6.entity.poi.PoiLocationEntity;
import com.ccrfid.rmc6.lbservice3.manager.ClientManager;
import com.ccrfid.rmc6.lbservice3.mq.MsgDispatcher;
import com.ccrfid.rmc6.pojo.Constants;
import com.ccrfid.rmc6.pojo.dto.*;
import com.ccrfid.rmc6.pojo.dto.personnel.PrisonerStatisticDto;
import com.ccrfid.rmc6.pojo.param.PageParam;
import com.ccrfid.rmc6.pojo.param.SortParam;
import com.ccrfid.rmc6.repository.search.Criterion;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.resource.auth.pojo.UserPrincipal;
import com.ccrfid.rmc6.service.personnel.MutualGroupService;
import com.ccrfid.rmc6.service.personnel.PersonnelService;
import com.ccrfid.rmc6.service.personnel.PersonnelTypeService;
import com.ccrfid.rmc6.service.sys.DictService;
import com.ccrfid.rmc6.service.sys.OrgService;
import com.ccrfid.rmc6.service.sys.RoomService;
import com.ccrfid.rmc6.util.DateUtil;
import com.ccrfid.rmc6.util.GeomUtil;
import com.ccrfid.rmc6.util.RegexUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.util.StringUtils;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Path("personnels")
@Produces(MediaType.APPLICATION_JSON)
public class PersonnelResource {
    private static final Logger logger = LoggerFactory.getLogger(PersonnelResource.class);
    @Context
    private SecurityContext securityContext;
    @Autowired
    private PersonnelService personnelService;
    @Autowired
    private OrgService orgService;
    @Autowired
    private DictService dictService;
    @Autowired
    private RoomService roomService;
    @Autowired
    private MsgDispatcher msgDispatcher;
    @Autowired
    private MutualGroupService mutualGroupService;
    @Autowired
    private PersonnelTypeService personnelTypeService;
    @Autowired
    private ClientManager clientManager;

    @GET
    public List<PersonnelEntity> getPersonnelWithCard() {
        return personnelService.getPersonnelListByCardNumberNotNull();
    }

    @GET
    @Path("all")
    public List<PersonnelEntity> getAllPersonnelsEnabled() {
        return personnelService.getAllPersonnelsEnabled();
    }

    @GET
    @Path("search-all")
    public List<PersonnelView> searchAll(@QueryParam("q") String queryStr,
                                         @QueryParam("orgId") Long orgId,
                                         @QueryParam("personnelId") Long personnelId,
                                         @QueryParam("personnelType") List<Integer> personnelTypeList,
                                         @QueryParam("enabled") Integer enabled,
                                         @QueryParam("onlineStatus") Integer onlineStatus,
                                         @BeanParam SortParam sortParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(queryStr)) {
            if (RegexUtil.maybeCardNumber(queryStr)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, Integer.parseInt(queryStr)));
            } else if (RegexUtil.isPersonnelSn(queryStr)) {
                criteria.add(new Criterion("personnelSn", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.isIdNumber(queryStr)) {
                criteria.add(new Criterion("idNumber", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.maybeNameAcronym(queryStr)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, queryStr + '%'));
            } else {
                //if (RegexUtil.containChinese(queryStr))
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + queryStr + '%'));
            }
        }
        if (personnelId != null) {
            criteria.add(new Criterion("id", Criterion.Operator.EQ, personnelId));
        }
        if (personnelTypeList != null && personnelTypeList.size() > 0) {
            List<Integer> typeList = new ArrayList<>();
            for (Integer personnelType : personnelTypeList) {
                typeList.addAll(dictService.getDictAndSubDictIdListById(personnelType));
            }
            criteria.add(new Criterion("personnelType", Criterion.Operator.IN, typeList));
        }
        if (orgId != null) {
            if (orgId > 0) {
                criteria.add(new Criterion("orgId", Criterion.Operator.EQ, orgId));
            } else {
                criteria.add(new Criterion("orgId", Criterion.Operator.NULL, orgId));
            }
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        } else {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, 1));
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        List<PersonnelView> list;
        if (sortParam.getOrders() != null && sortParam.getOrders().size() > 0) {
            list = personnelService.getPersonnelInfoList(criteria, Sort.by(sortParam.getOrders()));
        } else {
            list = personnelService.getPersonnelInfoList(criteria, Sort.by(new ArrayList<>()));
        }
        return list;
    }

    @GET
    @Path("search2")
    public Page<PersonnelView> Search2(@QueryParam("q") String queryStr,
                                       @QueryParam("orgId") Long orgId,
                                       @QueryParam("personnelType") List<Integer> personnelTypeList,
                                       @QueryParam("enabled") Integer enabled,
                                       @QueryParam("onlineStatus") Integer onlineStatus,
                                       @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(queryStr)) {
            if (RegexUtil.maybeCardNumber(queryStr)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, Integer.parseInt(queryStr)));
            } else if (RegexUtil.isPersonnelSn(queryStr)) {
                criteria.add(new Criterion("personnelSn", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.isIdNumber(queryStr)) {
                criteria.add(new Criterion("idNumber", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.maybeNameAcronym(queryStr)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, queryStr + '%'));
            } else {
                //if (RegexUtil.containChinese(queryStr))
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + queryStr + '%'));
            }
        }
        if (personnelTypeList != null && personnelTypeList.size() > 0) {
            List<Integer> typeList = new ArrayList<>();
            for (Integer personnelType : personnelTypeList) {
                typeList.addAll(dictService.getDictAndSubDictIdListById(personnelType));
            }
            criteria.add(new Criterion("personnelType", Criterion.Operator.IN, typeList));
        }
        if (orgId != null) {
            if (orgId > 0) {
                List<Long> idList = orgService.getSubOrgIdList(orgId);
                criteria.add(new Criterion("orgId", Criterion.Operator.IN, idList));
            } else {
                criteria.add(new Criterion("orgId", Criterion.Operator.NULL, orgId));
            }
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        Page<PersonnelView> page = personnelService.getPersonnelInfoPage(criteria, pageRequest);
        return page;
    }

    @GET
    @Path("search")
    public Page<PersonnelView> getPersonnelInfoPage(@QueryParam("personnelName") String personnelName,
                                                    @QueryParam("nameAcronym") String nameAcronym,
                                                    @QueryParam("personnelSn") String personnelSn,
                                                    @QueryParam("idNumber") String idNumber,
                                                    @QueryParam("cardNumber") Long cardNumber,
                                                    @QueryParam("orgId") Long orgId,
                                                    @QueryParam("personnelType") List<Integer> personnelTypeList,
                                                    @QueryParam("enabled") Integer enabled,
                                                    @QueryParam("onlineStatus") Integer onlineStatus,
                                                    @QueryParam("personnelCategory") String personnelCategory,
                                                    @QueryParam("hexNumber") String hexNumber,
                                                    @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (personnelName != null) {
            criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + personnelName + '%'));
        }
        if (nameAcronym != null) {
            criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, '%' + nameAcronym + '%'));
        }
        if (personnelSn != null) {
            criteria.add(new Criterion("personnelSn", Criterion.Operator.LIKE, '%' + personnelSn + '%'));
        }
        if (idNumber != null) {
            criteria.add(new Criterion("idNumber", Criterion.Operator.LIKE, '%' + idNumber + '%'));
        }
        if (cardNumber != null) {
            criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, cardNumber));
        }
        if (hexNumber != null) {
            criteria.add(new Criterion("hexNumber", Criterion.Operator.LIKE, '%' + hexNumber + '%'));

        }
        if (personnelTypeList != null && personnelTypeList.size() > 0) {
            List<Integer> typeList = new ArrayList<>();
            for (Integer personnelType : personnelTypeList) {
                typeList.addAll(dictService.getDictAndSubDictIdListById(personnelType));
            }
            criteria.add(new Criterion("personnelType", Criterion.Operator.IN, typeList));
        }
        if (orgId != null) {
            if (orgId > 0) {
                List<Long> idList = orgService.getSubOrgIdList(orgId);
                criteria.add(new Criterion("orgId", Criterion.Operator.IN, idList));
            } else {
                criteria.add(new Criterion("orgId", Criterion.Operator.NULL, orgId));
            }
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        if (personnelCategory != null) {
            criteria.add(new Criterion("personnelCategory", Criterion.Operator.LIKE, '%' + personnelCategory + '%'));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        Page<PersonnelView> page = personnelService.getPersonnelInfoPage(criteria, pageRequest);
        return page;
    }

    @GET
    @Path("prisoner/search")
    public Page<PersonnelPrisonerView> getPrisonerInfoPage(@QueryParam("personnelName") String personnelName,
                                                           @QueryParam("nameAcronym") String nameAcronym,
                                                           @QueryParam("personnelSn") String personnelSn,
                                                           @QueryParam("idNumber") String idNumber,
                                                           @QueryParam("cardNumber") String cardNumber,
                                                           @QueryParam("cardSn") String cardSn,
                                                           @QueryParam("orgId") Long orgId,
                                                           @QueryParam("enabled") Integer enabled,
                                                           @QueryParam("prisonerType") Integer prisonerType,
                                                           @QueryParam("caseTypeValue") String caseTypeValue,
                                                           @QueryParam("comeTime") String comeTimeStr,
                                                           @QueryParam("outTime") String outTimeStr,
                                                           @QueryParam("onlineStatus") Integer onlineStatus,
                                                           @QueryParam("heartRateMin") Integer heartRateMin,
                                                           @QueryParam("heartRateMax") Integer heartRateMax,
                                                           @QueryParam("personnelCategory") String personnelCategory,
                                                           @QueryParam("cutoffStatus") Integer cutoffStatus,
                                                           @QueryParam("lowpowerStatus") Integer lowpowerStatus,
                                                           @QueryParam("hexNumber") String hexNumber,
                                                           @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(personnelName)) {
            if (RegexUtil.maybeNameAcronym(personnelName)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, personnelName + '%'));
            } else {
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + personnelName + '%'));
            }
        }
        if (nameAcronym != null) {
            criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, '%' + nameAcronym + '%'));
        }
        if (personnelSn != null) {
            criteria.add(new Criterion("personnelSn", Criterion.Operator.LIKE, '%' + personnelSn + '%'));
        }
        if (idNumber != null) {
            criteria.add(new Criterion("idNumber", Criterion.Operator.LIKE, '%' + idNumber + '%'));
        }
        if (cardNumber != null) {
            if (RegexUtil.maybeCardNumber(cardNumber)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, cardNumber));
            } else {
                criteria.add(new Criterion("cardSn", Criterion.Operator.LIKE, '%' + cardNumber + '%'));
            }
        }
        if (cardSn != null) {
            criteria.add(new Criterion("cardSn", Criterion.Operator.LIKE, '%' + cardSn + '%'));
        }
        if (hexNumber != null) {
            criteria.add(new Criterion("hexNumber", Criterion.Operator.LIKE, '%' + hexNumber + '%'));
        }
        if (orgId != null) {
            if (orgId > 0) {
                List<Long> idList = orgService.getSubOrgIdList(orgId);
                criteria.add(new Criterion("orgId", Criterion.Operator.IN, idList));
            } else {
                criteria.add(new Criterion("orgId", Criterion.Operator.NULL, orgId));
            }
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        }
        if (prisonerType != null) {
            switch (prisonerType) {
                case 150:   //死刑犯
                    criteria.add(new Criterion("isDeathPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 151:   //重刑犯
                    criteria.add(new Criterion("isMajorCriminalOffender", Criterion.Operator.EQ, 1));
                    break;
                case 152:   //危重病犯
                    criteria.add(new Criterion("isInfectedPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 153:   //重点人员
                    criteria.add(new Criterion("isFocusedPrisoner", Criterion.Operator.EQ, 1));
                    break;
            }
        }
        if (caseTypeValue != null) {
            criteria.add(new Criterion("caseTypeValue", Criterion.Operator.LIKE, '%' + caseTypeValue + '%'));
        }
        if (comeTimeStr != null && comeTimeStr.contains(",")) {
            String[] timeValues = comeTimeStr.split(",");
            Date start = DateUtil.parseDateTimeStr(timeValues[0] + " 00:00:00");
            Date end = DateUtil.parseDateTimeStr(timeValues[1] + " 23:59:59");
            criteria.add(new Criterion("comeTime", Criterion.Operator.GTE, start));
            criteria.add(new Criterion("comeTime", Criterion.Operator.LTE, end));
        }
        if (outTimeStr != null && outTimeStr.contains(",")) {
            String[] timeValues = outTimeStr.split(",");
            Date start = DateUtil.parseDateTimeStr(timeValues[0] + " 00:00:00");
            Date end = DateUtil.parseDateTimeStr(timeValues[1] + " 23:59:59");
            criteria.add(new Criterion("outTime", Criterion.Operator.GTE, start));
            criteria.add(new Criterion("outTime", Criterion.Operator.LTE, end));
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        if (heartRateMin != null) {
            criteria.add(new Criterion("heartRate", Criterion.Operator.GTE, heartRateMin));
        }
        if (heartRateMax != null) {
            criteria.add(new Criterion("heartRate", Criterion.Operator.LTE, heartRateMax));
        }
        if (personnelCategory != null) {
            criteria.add(new Criterion("personnelCategory", Criterion.Operator.LIKE, '%' + personnelCategory + '%'));
        }
        if (cutoffStatus != null) {
            criteria.add(new Criterion("cutoffStatus", Criterion.Operator.EQ, cutoffStatus));
        }
        if(lowpowerStatus != null){
            criteria.add(new Criterion("lowpowerStatus", Criterion.Operator.EQ, lowpowerStatus));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        Page<PersonnelPrisonerView> page = personnelService.getPrisonerInfoPage(criteria, pageRequest);
        return page;
    }

    @GET
    @Path("prisoner/search2")
    public Page<PersonnelPrisonerView> prisonerSearch2(@QueryParam("q") String queryStr,
                                                       @QueryParam("orgId") Long orgId,
                                                       @QueryParam("enabled") Integer enabled,
                                                       @QueryParam("prisonerType") Integer prisonerType,
                                                       @QueryParam("caseTypeValue") String caseTypeValue,
                                                       @QueryParam("comeTime") String comeTimeStr,
                                                       @QueryParam("outTime") String outTimeStr,
                                                       @QueryParam("onlineStatus") Integer onlineStatus,
                                                       @QueryParam("heartRateMin") Integer heartRateMin,
                                                       @QueryParam("heartRateMax") Integer heartRateMax,
                                                       @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(queryStr)) {
            if (RegexUtil.maybeCardNumber(queryStr)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, Integer.parseInt(queryStr)));
            } else if (RegexUtil.isPersonnelSn(queryStr)) {
                criteria.add(new Criterion("personnelSn", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.isIdNumber(queryStr)) {
                criteria.add(new Criterion("idNumber", Criterion.Operator.EQ, queryStr));
            } else if (RegexUtil.maybeNameAcronym(queryStr)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, queryStr + '%'));
            } else {
                //if (RegexUtil.containChinese(queryStr))
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + queryStr + '%'));
            }
        }
        if (orgId != null) {
            if (orgId > 0) {
                List<Long> idList = orgService.getSubOrgIdList(orgId);
                criteria.add(new Criterion("orgId", Criterion.Operator.IN, idList));
            } else {
                criteria.add(new Criterion("orgId", Criterion.Operator.NULL, orgId));
            }
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        }
        if (prisonerType != null) {
            switch (prisonerType) {
                case 150:   //死刑犯
                    criteria.add(new Criterion("isDeathPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 151:   //重刑犯
                    criteria.add(new Criterion("isMajorCriminalOffender", Criterion.Operator.EQ, 1));
                    break;
                case 152:   //危重病犯
                    criteria.add(new Criterion("isInfectedPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 153:   //重点人员
                    criteria.add(new Criterion("isFocusedPrisoner", Criterion.Operator.EQ, 1));
                    break;
            }
        }
        if (caseTypeValue != null) {
            criteria.add(new Criterion("caseTypeValue", Criterion.Operator.LIKE, '%' + caseTypeValue + '%'));
        }
        if (comeTimeStr != null && comeTimeStr.contains(",")) {
            String[] timeValues = comeTimeStr.split(",");
            Date start = DateUtil.parseDateTimeStr(timeValues[0] + " 00:00:00");
            Date end = DateUtil.parseDateTimeStr(timeValues[1] + " 23:59:59");
            criteria.add(new Criterion("comeTime", Criterion.Operator.GTE, start));
            criteria.add(new Criterion("comeTime", Criterion.Operator.LTE, end));
        }
        if (outTimeStr != null && outTimeStr.contains(",")) {
            String[] timeValues = outTimeStr.split(",");
            Date start = DateUtil.parseDateTimeStr(timeValues[0] + " 00:00:00");
            Date end = DateUtil.parseDateTimeStr(timeValues[1] + " 23:59:59");
            criteria.add(new Criterion("outTime", Criterion.Operator.GTE, start));
            criteria.add(new Criterion("outTime", Criterion.Operator.LTE, end));
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        if (heartRateMin != null) {
            criteria.add(new Criterion("heartRate", Criterion.Operator.GTE, heartRateMin));
        }
        if (heartRateMax != null) {
            criteria.add(new Criterion("heartRate", Criterion.Operator.LTE, heartRateMax));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        Page<PersonnelPrisonerView> page = personnelService.getPrisonerInfoPage(criteria, pageRequest);
        return page;
    }

    @GET
    @Path("{id}/detail")
    public PersonnelView getPersonnelDetailById(@PathParam("id") Long personnelId) {
        PersonnelView personnelView = personnelService.getPersonnelDetailById(personnelId);
        return personnelView;
    }

    @Secured
    @GET
    @Path("prisoners2")
    public List<PersonnelPrisonerView> getPrisonerList2(@QueryParam("enabled") Integer enabled,
                                                        @QueryParam("comeTimeStart") Timestamp comeTimeStart,
                                                        @QueryParam("comeTimeStop") Timestamp comeTimeStop,
                                                        @QueryParam("prisonerType") Integer prisonerType,
                                                        @QueryParam("onlineStatus") Integer onlineStatus,
                                                        @BeanParam SortParam sortParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        Long accountOrgId = ((UserPrincipal) securityContext.getUserPrincipal()).getOrgId();
        if (accountOrgId != null) {
            List<Long> idList = orgService.getSubOrgIdList(accountOrgId);
            criteria.add(new Criterion("orgId", Criterion.Operator.IN, idList));
        }
        if (enabled != null) {
            criteria.add(new Criterion("enabled", Criterion.Operator.EQ, enabled));
        }
        if (comeTimeStart != null) {
            criteria.add(new Criterion("comeTime", Criterion.Operator.GTE, comeTimeStart));
        }
        if (comeTimeStop != null) {
            criteria.add(new Criterion("comeTime", Criterion.Operator.LTE, comeTimeStop));
        }
        if (prisonerType != null) {
            switch (prisonerType) {
                case 150:   //死刑犯
                    criteria.add(new Criterion("isDeathPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 151:   //重刑犯
                    criteria.add(new Criterion("isMajorCriminalOffender", Criterion.Operator.EQ, 1));
                    break;
                case 152:   //危重病犯
                    criteria.add(new Criterion("isInfectedPrisoner", Criterion.Operator.EQ, 1));
                    break;
                case 153:   //重点人员
                    criteria.add(new Criterion("isFocusedPrisoner", Criterion.Operator.EQ, 1));
                    break;
            }
        }
        if (onlineStatus != null) {
            criteria.add(new Criterion("onlineStatus", Criterion.Operator.EQ, onlineStatus));
        }
        List<PersonnelPrisonerView> list;
        if (sortParam.getOrders() != null && sortParam.getOrders().size() > 0) {
            list = personnelService.getPrisonerList(criteria, Sort.by(sortParam.getOrders()));
        } else {
            list = personnelService.getPrisonerList(criteria, Sort.by(new ArrayList<>()));
        }
        return list;
    }

    @Secured
    @GET
    @Path("prisoners")
    public List<PersonnelPrisonerView> getPrisonerList(@QueryParam("enabled") Integer enabled,
                                                       @QueryParam("comeTimeStart") Timestamp comeTimeStart,
                                                       @QueryParam("comeTimeStop") Timestamp comeTimeStop,
                                                       @QueryParam("prisonerType") Integer prisonerType,
                                                       @QueryParam("onlineStatus") Integer onlineStatus,
                                                       @BeanParam SortParam sortParam) {
        Long accountOrgId = ((UserPrincipal) securityContext.getUserPrincipal()).getOrgId();
        List<PersonnelPrisonerView> list =
                personnelService.getPrisonerList(accountOrgId, enabled, comeTimeStart, comeTimeStop, prisonerType, onlineStatus, sortParam);
        return list;
    }

    @GET
    @Path("prisoner/{id}/detail")
    public PersonnelPrisonerView getPrisonerDetailById(@PathParam("id") Long personnelId) {
        PersonnelPrisonerView prisonerView = personnelService.getPrisonerDetailById(personnelId);
        return prisonerView;
    }

    @GET
    @Path("{id}")
    public PersonnelEntity getPersonnelById(@PathParam("id") Long personnelId) {
        PersonnelEntity personnelEntity = personnelService.getPersonnelById(personnelId);
        return personnelEntity;
    }

    @PUT
    @Path("{id}")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelEntity updatePersonnel(@PathParam("id") Long personnelId, PersonnelEntity entity)
            throws AppException {
        PersonnelEntity personnelEntity = personnelService.updatePersonnel(personnelId, entity);
        return personnelEntity;
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelEntity createPersonnel(PersonnelEntity entity) throws AppException {
        PersonnelEntity personnelEntity = personnelService.createPersonnel(entity);
        return personnelEntity;
    }

    @POST
    @Path("prisoner")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelEntity createPrisoner(NewPrisonerDto dto) throws AppException {
        PersonnelEntity personnelEntity = personnelService.createPrisoner(dto);
        return personnelEntity;
    }

    @DELETE
    @Consumes(MediaType.APPLICATION_JSON)
    public int deletePersonnels(List<Long> idList) throws AppException {
        if (idList == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        return personnelService.deletePersonnels(idList);
    }

    @GET
    @Path("{id}/photo")
    @Produces("image/jpeg")
    public byte[] getPersonnelPhoto(@PathParam("id") Long personnelId) {
        return personnelService.getPersonnelPhoto(personnelId);
    }

    @PUT
    @Path("{id}/photo")
    @Consumes(MediaType.APPLICATION_OCTET_STREAM)
    public Boolean updatePersonnelPhoto(@PathParam("id") Long personnelId, byte[] image)
            throws AppException {
        return personnelService.updatePersonnelPhoto(personnelId, image);
    }

    @PUT
    @Path("{personnelId}/binding/{cardNumber}")
    public Boolean bindPersonnelCard(@PathParam("personnelId") Long personnelId,
                                     @PathParam("cardNumber") Long cardNumber) throws AppException {
        personnelService.bindPersonnelCard(personnelId, cardNumber);
        msgDispatcher.bindPersonnelCard(personnelId, cardNumber);
        return true;
    }

    @DELETE
    @Path("{personnelId}/binding/{cardNumber}")
    public Boolean unBindPersonnelCard(@PathParam("personnelId") Long personnelId,
                                       @PathParam("cardNumber") Long cardNumber) throws AppException {
        personnelService.unBindPersonnelCard(personnelId, cardNumber);
        msgDispatcher.unBindPersonnelCard(personnelId, cardNumber);
        return true;
    }

    @GET
    @Path("map")
    public List<LocatorPersonnelCount> getPersonnelMap(@QueryParam("personnelType") Integer personnelType,
                                                       @QueryParam("floorNumber") Integer floorNumber) {
        if (personnelType != null) {
            return personnelService.getPersonnelMap(personnelType, floorNumber);
        } else {
            return null;
        }
    }

    @GET
    @Path("prisoner/map")
    public List<LocatorPersonnelCount> getPrisonerMap(@QueryParam("prisonerType") Integer prisonerType,
                                                      @QueryParam("floorNumber") Integer floorNumber) {
        if (prisonerType != null) {
            return personnelService.getPrisonerMap(prisonerType, floorNumber);
        } else {
            return null;
        }
    }

    @GET
    @Path("{personnelId}/position")
    public PositionDto getPersonnelPosition(@PathParam("personnelId") Long personnelId) {
        return personnelService.getPersonnelPosition(personnelId);
    }

    @GET
    @Path("{personnelId}/level3-location")
    public PoiLocationEntity getPersonnel3LevelLocation(@PathParam("personnelId") Long personnelId) {
        return personnelService.getPersonnel3LevelLocation(personnelId);
    }

    @GET
    @Path("{personnelId}/move-line")
    public List<MoveLineDto> getPersonnelMoveLine(@PathParam("personnelId") Long personnelId,
                                                  @QueryParam("startTime") Timestamp startTime,
                                                  @QueryParam("endTime") Timestamp endTime) {
        return personnelService.getPersonnelMoveLine(personnelId, startTime, endTime);
    }

    @GET
    @Path("level3-location-activitiy/trackId/{trackId}")
    public PersonnelLocationActivityDto getLevel3LocationActivity(@PathParam("trackId") Long trackId) {
        return personnelService.getLevel3LocationActivity(trackId);
    }

    @GET
    @Path("{personnelId}/level3-move-locations")
    public List<MoveInLocationDto> getPersonnelMoveLocationList(@PathParam("personnelId") Long personnelId,
                                                                @QueryParam("startTime") Timestamp startTime,
                                                                @QueryParam("endTime") Timestamp endTime) {
        return roomService.getPersonnelMoveLocationList(personnelId,
                DateUtil.toDateTimeStr(startTime), DateUtil.toDateTimeStr(endTime));
    }

    @GET
    @Path("statistic")
    public List<PersonnelStatisticDto> getPersonnelStatisticList() {
        return personnelService.getPersonnelStatisticList();
    }

    @Secured
    @GET
    @Path("prisoner-statistic")
    public PrisonerStatisticDto getPrisonerStatistic() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        return personnelService.getPrisonerStatistic(userPrincipal.getOrgId());
    }

    //查询某区域内的实时人员
    @GET
    @Path("real-position/{fn}/{x1},{y1}-{x2},{y2}")
    public List<PersonnelPositionView> getPersonnelsInPolygon(@PathParam("fn") int floorNumber,
                                                              @PathParam("x1") double x1, @PathParam("y1") double y1,
                                                              @PathParam("x2") double x2, @PathParam("y2") double y2) {
        List<PersonnelPositionView> list =
                personnelService.getPersonnelsInPolygon(floorNumber, GeomUtil.INSTANCE.createPolygon(x1, y1, x2, y2));
        list.parallelStream().forEach(personnel -> {
            if (isWorker(personnel.getPersonnelType())) {
                personnel.setPersonnelType(Constants.PERSONNEL_TYPE.WORKER.id);
            }
        });
        return list;
    }

    private boolean isWorker(Integer personnelType) {
        if (personnelType != null
                && (personnelType.equals(Constants.PERSONNEL_TYPE.POLICE.id)
                || personnelType.equals(Constants.PERSONNEL_TYPE.WEN_ZHI.id)
                || personnelType.equals(Constants.PERSONNEL_TYPE.TE_QIN.id)
                || personnelType.equals(Constants.PERSONNEL_TYPE.MEDICAL_WORKER.id)
                || personnelType.equals(Constants.PERSONNEL_TYPE.DUSTMAN.id)
                || personnelType.equals(Constants.PERSONNEL_TYPE.WU_JING.id))) {
            return true;
        }
        return false;
    }

    //查询互监组
    @GET
    @Path("mutual-groups")
    public Page<PersonnelMutualGroupEntity> getPersonnelMutualGroupPage(@QueryParam("groupName") String groupName,
                                                                        @QueryParam("groupType") String groupType,
                                                                        @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(groupName)) {
            criteria.add(new Criterion("groupName", Criterion.Operator.LIKE, '%' + groupName + '%'));
        }
        if (groupType != null) {
            criteria.add(new Criterion("groupType", Criterion.Operator.EQ, groupType));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return mutualGroupService.getPersonnelMutualGroupPage(criteria, pageRequest);
    }

    //添加互监组
    @POST
    @Path("mutual-groups")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelMutualGroupEntity createPersonnelMutualGroup(PersonnelMutualGroupEntity entity) throws AppException {
        return mutualGroupService.createPersonnelMutualGroup(entity);
    }

    //修改互监组
    @PUT
    @Path("mutual-groups/{groupId}")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelMutualGroupEntity updatePersonnelMutualGroup(@PathParam("groupId") Long groupId,
                                                                 PersonnelMutualGroupEntity entity) throws AppException {
        return mutualGroupService.updatePersonnelMutualGroup(groupId, entity);
    }

    //删除互监组
    @DELETE
    @Path("mutual-groups/{groupId}")
    public Boolean deletePersonnelMutualGroup(@PathParam("groupId") Long groupId) throws AppException {
        return mutualGroupService.deletePersonnelMutualGroup(groupId);
    }

    //获取互监组相关人员
    @GET
    @Path("mutual-groups/{groupId}/members")
    public List<PersonnelMutualGroupMemberEntity> getPersonnelMutualGroupMemberList(@PathParam("groupId") Long groupId) {
        return mutualGroupService.getPersonnelMutualGroupMemberList(groupId);
    }

    //向互监组中加入某个人员
    @POST
    @Path("mutual-groups/{groupId}/members")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelMutualGroupMemberEntity createPersonnelMutualGroupMember(@PathParam("groupId") Long groupId,
                                                                             PersonnelMutualGroupMemberEntity entity)
            throws AppException {
        return mutualGroupService.createPersonnelMutualGroupMember(groupId, entity);
    }

    //从互监组中删除某个人员
    @DELETE
    @Path("mutual-groups/{groupId}/members/{memberId}")
    public Boolean deletePersonnelMutualGroupMember(@PathParam("groupId") Long groupId,
                                                    @PathParam("memberId") Long memberId) throws AppException {
        return mutualGroupService.deletePersonnelMutualGroupMember(groupId, memberId);
    }

    //增加人员所属类别
    @POST
    @Path("personnelType/create")
    public PersonnelTypeEntity savePersonnelPrisonerType(PersonnelTypeEntity personnelTypeEntity) throws AppException {
        return personnelTypeService.createPeronnelType(personnelTypeEntity);
    }

    //修改人员所属类别
    @PUT
    @Path("personnelType/{id}/update")
    @Consumes(MediaType.APPLICATION_JSON)
    public PersonnelTypeEntity updatePersonnelType(@PathParam("id") Long id,
                                                   PersonnelTypeEntity entity) throws AppException {
        return personnelTypeService.updatePersonnelType(id, entity);
    }

    //删除人员所属类别
    @DELETE
    @Path("personnelType/{id}/delete")
    public Boolean deletePersonnelType(@PathParam("id") Long id) throws AppException {
        return personnelTypeService.deletePersonnelType(id);
    }

    //查询人员所属类别
    @GET
    @Path("personnelType/search")
    public Page<PersonnelTypeEntity> getPersonnelType(@QueryParam("personnelTypeName") String personnelTypeName,
                                                      @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(personnelTypeName)) {
            criteria.add(new Criterion("personnelTypeName", Criterion.Operator.LIKE, '%' + personnelTypeName + '%'));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return personnelTypeService.getPersonnelType(criteria, pageRequest);
    }

    //按区域的人数统计
    @GET
    @Path("get-personnel-count-by-location")
    public List<AreaCateGoryLocationDto> getPersonnelArea(@QueryParam("locationSnList") String locationSnList) {
        return personnelService.getPersonnelArea(locationSnList);
    }

    //按标签状态的标签数统计
    @GET
    @Path("get-card-status")
    public CardStatusDto getCardStatus() {
        return personnelService.getCardStatus();
    }

    //按标签状态的标签数统计-怀化
    @Secured
    @GET
    @Path("get-card-status-huaihua")
    public CardStatusDto getCardStatusHuaihua() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        return personnelService.getCardStatusHuaihua(userPrincipal.getOrgId());
    }

    //获取各类人员总数
    @GET
    @Path("get-personnel-count-type")
    public List<PersonelAllTypeCountDto> getPersonlTypeCount() {
        return personnelService.getPersonnelTypeCount();
    }

    //1.4按人员类型的在册人数统计
    @GET
    @Path("get-zc-personnel-count")
    public ZcPersonnelDto getZcPersonnelCount() {
        return personnelService.getZCPeronnelCount();
    }

    //1.6按人员类型的在线离线定位人数统计
    @GET
    @Path("get-personnel-count-by-onlineStatus")
    public List<PersonnelOnlineCountDto> getPeronnelCountByOnlineStatu() {
        return personnelService.getPersonnelOnlineCount();
    }

    //1.2按区域类型的人数统计
    @Secured
    @GET
    @Path("get-personnel-count-by-locator")
    public PersonnelCountByLocationTotalDto getPersonnelCountByLocator(@QueryParam("personnelType") Integer personnelType,
                                                                       @QueryParam("locationId") Integer locationId,
                                                                       @QueryParam("orgId") Long orgId) {
        if(orgId == null){
            UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
            orgId = userPrincipal.getOrgId();
        }
        return personnelService.getPersonnelCountByLocator2(personnelType, locationId, orgId);
    }

    //获取重点人员在册数
    @Secured
    @GET
    @Path("get-focused-prisoner-count")
    public Long getFocusedPrisonerCount() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        return personnelService.getFocusedPrisonerCount(userPrincipal.getOrgId());
    }

    //按组织机构获取人数统计
    @GET
    @Path("get-personnel-count-by-org/{orgId}")
    public List<PersonnelCountByOrgDto> getPersonnelCountByOrg(@PathParam("orgId") Long orgId) {

        return personnelService.getPersonnelCountByOrg(orgId);
    }

    //按组织机构获取人数统计
    @GET
    @Path("get-personnel-count-detail-by-org/{orgId}")
    public List<PersonnelCountDetailByOrgDto> getPersonnelCountDetailByOrg(@PathParam("orgId") Long orgId) {

        return personnelService.getPersonnelCountDetailByOrg(orgId);
    }

    //获取在线离线人员详情
    @GET
    @Path("get-personnel-detail/{orgId}")
    public List<PersonnelDetailByOrgDto> getPersonnelDetailByOrg(@PathParam("orgId") Long orgId) {
        return personnelService.getPersonnelDetailByOrg(orgId);
    }


    //获取区域类型下所有区域的人数统计
    @Secured
    @GET
    @Path("get-personnel-by-locationType/{locationType}")
    public Page<PersonnelCountByLocationTypeDto> getPersonnelCountByLocationType(@PathParam("locationType") int locationType, @BeanParam PageParam pageParam) {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return personnelService.getPersonnelCountByLocationType(locationType, orgId, pageRequest);
    }

    //APP首页接口
    @Secured
    @GET
    @Path("get-app-homepagedata")
    public PersonnelCountForAppDtp getAppHomePageData() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        Long notifyPersonnelId = userPrincipal.getPersonnelId();
        return personnelService.getAppHomePageData(orgId, notifyPersonnelId);
    }

    //app区域类型得定位人数
    @Secured
    @GET
    @Path("get-count-by-locationType")
    public List<PersonnelCountByLocationTypeDto> getCountByLocationType() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        return personnelService.getCountByLocationType(orgId);
    }


    //根据区域ID获取下属人员详情
    @Secured
    @GET
    @Path("{locationId}/detail-personnels")
    public Page<LocationPersonnelDetailForAppDto> getActualPersonnelsInfo(@PathParam("locationId") Long locationId, @BeanParam PageParam pageParam) {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return personnelService.getActualPersonnelsInfoInLocation(locationId, orgId, pageRequest);
    }

    //获取APP最新版本号
    @GET
    @Path("get-app-version")
    public String getAppVersion() {
        return personnelService.getAppVersion();
    }

    //获取区域类型下所有区域的人数详情
    @Secured
    @GET
    @Path("get-personnel-detail-by-locationType/{locationType}")
    public Page<LocationPersonnelDetailForAppDto> getPersonnelDetailByLocationType(@PathParam("locationType") int locationType, @BeanParam PageParam pageParam) {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return personnelService.getPersonnelDetailByLocatorType(locationType, orgId, pageRequest);
    }

    //app人员查询
    @Secured
    @GET
    @Path("app-personnel/search")
    public Page<LocationPersonnelDetailForAppDto> searchAppPersonnel(@QueryParam("personnelName") String personnelName,
                                                                     @QueryParam("cardNumber") Long cardNumber,
                                                                     @BeanParam PageParam pageParam) {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return personnelService.getPersonnelForApp(personnelName, cardNumber, orgId, pageRequest);
    }

    //获取定位异常人员详情
    @Secured
    @GET
    @Path("untreated-person-detail")
    public List<UntreatedPersonDetailDto> getUntreatedPersonDetail() {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long orgId = userPrincipal.getOrgId();
        return personnelService.getUntreatedPersonDetail(orgId);
    }

    //获取区域类型下的人员详情（怀化--分帐号）
    @Secured
    @GET
    @Path("get-personnel-detail-by-typeName")
    public List<LocationPersonnelDetailDto> getPersonnelDetail(@QueryParam("locationTypeList") String typeList,
                                                               @QueryParam("flag") Integer flag,
                                                               @QueryParam("orgId") Long orgId) {
        if (orgId == null) {
            UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
            orgId = userPrincipal.getOrgId();
        }
        return personnelService.getPersonDetail2(orgId, typeList, flag);
    }

    @Secured
    @GET
    @Path("get-personnel-detail-by-typeName1")
    public List<LocationPersonnelDetailDto> getPersonnelDetail1(@QueryParam("locationTypeList") String typeList,
                                                               @QueryParam("flag") Integer flag,
                                                               @QueryParam("orgId") Long orgId) {
        if (orgId == null) {
            UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
            orgId = userPrincipal.getOrgId();
        }
        return personnelService.getPersonDetail(orgId, typeList, flag);
    }

    //APP获取人员告警信息
    @Secured
    @GET
    @Path("{personnelId}/alarm-record-for-app")
    public List<AlarmRecordForAppDto> getAlarmMsgToAppList(@PathParam("personnelId") Long personnelId) {
        return clientManager.getAlarmMsgToAppList(personnelId);
    }
}
